package com.n9.qqonline.sales.service;

import com.n9.db.util.GenericService;
import com.n9.qqonline.sales.entity.BuyMsg;
import com.n9.qqonline.sales.entity.ReadStatus;
import com.n9.qqonline.sales.entity.RecvMsg;
import com.n9.qqonline.sales.filter.RecvMsgFilter;
import org.apache.commons.codec.digest.DigestUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
import java.util.Objects;
import java.util.TreeMap;
import java.util.concurrent.Executor;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ScheduledThreadPoolExecutor;

/**
 * @author ice
 * @since 2019/3/6 19:06
 */
public class RecvMsgService {
    private static final Logger log = LoggerFactory.getLogger(RecvMsgService.class);
    private static final Logger msgLog = LoggerFactory.getLogger("recvMsgLog");

    private static final LinkedBlockingQueue<RecvMsg> msgs = new LinkedBlockingQueue<>();

    private static final Map<String, RecvMsgFilter> filters = new TreeMap<>();
    private static final Executor exec = new ScheduledThreadPoolExecutor(30);

    private volatile static boolean runFlag = true;

    static {
        start();
    }

    public void addFilter(String name, RecvMsgFilter filter) {
        filters.put(name, filter);
    }

    private static void start() {
        new Thread(){
            @Override
            public void run() {
                while(runFlag) {
                    try {
                        RecvMsg msg = msgs.take();
                        if(Objects.nonNull(msg)) {
                            ProcessRecvMsgTask task = new ProcessRecvMsgTask(msg);
                            exec.execute(task);
                        }
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }.start();
    }

    public static void shoutdown() {
        runFlag = false;
    }

    public void save(RecvMsg recvMsg) {
        try {
            msgs.put(recvMsg);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }


    static class ProcessRecvMsgTask implements Runnable {
        private RecvMsg recvMsg;

        public ProcessRecvMsgTask(RecvMsg recvMsg) {
            this.recvMsg = recvMsg;
        }

        @Override
        public void run() {
            try{
                msgLog.info("发送QQ:{},发送昵称:{},接收QQ:{},消息类型:{},接收群:{},接收群名称:{},消息时间:{},消息ID:{},消息内容:{}",
                        recvMsg.getSendQQUin(), recvMsg.getSendNick(), recvMsg.getRecvQQUin(), recvMsg.getMsgType().toString(),
                        recvMsg.getRecvGroupCode(), recvMsg.getRecvGroupName(), recvMsg.getRecvTime(), recvMsg.getMsgId(), recvMsg.getContent());

                boolean accept = true;
                for (Map.Entry<String, RecvMsgFilter> entry:filters.entrySet()) {
                    RecvMsgFilter filter = entry.getValue();
                    accept &= filter.accept(recvMsg);
                }

                if (accept) {
                    String sign = DigestUtils.md5Hex(recvMsg.getContent());
                    recvMsg.setSign(sign);

                    GenericService genericService = new GenericService();
                    final long count = genericService.count(String.format("SELECT COUNT(id) FROM BuyMsg WHERE sign = '%s'", sign));
                    genericService.execUpdate((session)->{
                        session.save(recvMsg);
                        if (count <= 0) {
                            BuyMsg buyMsg = new BuyMsg();
                            buyMsg.setCreateTime(new Date());
                            buyMsg.setReadStatus(ReadStatus.UN_READ);
                            buyMsg.setSign(recvMsg.getSign());
                            buyMsg.setContent(recvMsg.getContent());
                            buyMsg.setDay(new SimpleDateFormat("yyyy-MM-dd").format(buyMsg.getCreateTime()));
                            session.save(buyMsg);

                            BuyMsgReport.instance().incUnReadCount();
                        }
                    });
                } else {
                    msgLog.info("{}:被过滤", recvMsg.getMsgId());
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }


}
